package com.xunk.equipment.service.zhijia.service;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.xunk.common.core.constant.HttpStatus;
import com.xunk.common.core.domain.EquipmentResponse;
import com.xunk.common.core.utils.StringUtils;
import com.xunk.common.redis.service.RedisService;
import com.xunk.equipment.domain.EquipmentDO;
import com.xunk.equipment.mapper.EquipmentMapper;
import com.xunk.equipment.mapper.HomeMapper;
import com.xunk.equipment.service.BaseService;
import com.xunk.equipment.service.IEquipmentService;
import com.xunk.equipment.vo.response.WindowCurtainRresponse;
import com.xunk.equipment.websocket.WebsocketManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * @ProjectName: HIM
 * @Package: com.xunk.equipment.service.zhijia.service
 * @ClassName: UhomeWindowCurtainService
 * @Author: luanzhiwei
 * @Description: 智家窗帘电机
 * @Date: 2021/6/15 13:28
 * @Version: 1.0
 */
@Service(value = "uplus-window-curtain")
@Slf4j
public class UhomeWindowCurtainService implements IEquipmentService {

    @Autowired
    private ZhijiaService zhijiaService;
    @Autowired
    private BaseService baseService;
    @Autowired
    private EquipmentMapper equipmentMapper;
    @Autowired
    private RedisService redisService;

    @Autowired
    private HomeMapper homeMapper;


    /**
     * 获取设备当前状态值信息
     *
     * @param equipmentDO 当前设备信息，包含设备id，设备厂商
     * @return
     */
    @Override
    public EquipmentResponse getEquipmentInfo(EquipmentDO equipmentDO) {
        /*
        redis缓存的数据格式
        "shadowInfo": {
        "online": true,
        "onoffTimestamp": "1623718948387"
        }
        */

        String deviceSn = equipmentDO.getDeviceSn();
        final Long homeId = equipmentMapper.selectHomeIdByDeviceSn(deviceSn);
        Map<String, Object> cacheMap = zhijiaService.getShadowByDeviceSn(homeId, equipmentDO.getDeptId(), deviceSn);
        WindowCurtainRresponse response = new WindowCurtainRresponse();
        response.setDeviceName(equipmentDO.getDeviceName());
        response.setDeviceType(equipmentDO.getDeviceType());
        response.setDeviceSn(deviceSn);
        //reported 包含全部设备属性
        final Map reported = (Map) cacheMap.get("reported");
        //窗帘电机其他信息，例如当前开合比例等，可能是因为未设置行程，暂时取不到
        response.setPosition(Convert.toInt(reported.get("openDegree"), 0));
        final Boolean onOffStatus = Convert.toBool(reported.get("onOffStatus"));
        response.setOn(onOffStatus);
        response.setOnList(onList);
        response.setPositionRange(positionRange);

        final List<Map<String, Object>> module = (List<Map<String, Object>>) cacheMap.get("module");
        final Map moduleInfo = module.get(0);
        final Map info = (Map) moduleInfo.get("moduleInfos");
        final Optional<Map<String, Object>> first = module.stream().filter(item -> ObjectUtil.equals(item.get("moduleType"), "basemodule")).findFirst();
        if (first.isPresent()) {
            final Map<String, Object> firstMap = first.get();
            final Map firstInfo = (Map) firstMap.get("moduleInfos");
            response.setModel(Convert.toStr(firstInfo.get("hardwareType")));
        }
        response.setFirmWare(Convert.toStr(info.get("softwareVers")));
        response.setSerialNumber(Convert.toStr(cacheMap.get("deviceId")));
        response.setSupplier(equipmentDO.getSupplier());
        response.setCandidateModel(baseService.getCandidateModel(equipmentDO.getDeviceBaseId()));


        final Map shadowInfo = (Map) cacheMap.get("shadowInfo");
        response.setOnline(Convert.toBool(shadowInfo.get("online"), false));
        equipmentMapper.updateEquipmentOnline(equipmentDO.getDeviceSn(), response.getOnline() ? 1L : 0L);

        return response;
    }

    /**
     * 控制设备
     *
     * @param equipmentDO 当前设备信息，包含设备id，设备厂商
     * @param type        控制类型，如温度、开关、模式
     * @param value       操作目标值  如 20°(20)、open(true)、冷风模式(3)
     * @return
     */
    private Map<String, String> codeDict = new HashMap<String, String>() {{
        put("on", "onOffStatus");
        put("targetPosition", "openDegree");
    }};

    @Override
    public Boolean control(EquipmentDO equipmentDO, String type, String value) {
        boolean flag = false;
        type = codeDict.getOrDefault(type, "未知");
        if (StringUtils.equals(type, "openDegree")) {
            int v = Integer.parseInt(value);
            // 小于等于0，修正为直接关闭窗帘指令
            if (v <= 0) {
                type = "onOffStatus";
                value = "false";
            } else if (v > 100) {
                // 大于100，修正为100
                value = "100";
            }
        }
        flag = zhijiaService.control(equipmentDO, type, value);
//        switch (type) {
//            case "onOffStatus":
//                break;
//            case "openDegree":
//                flag = zhijiaService.control(equipmentDO, type, value);
//                break;
//            default:
//        }
//
//
//        if (StringUtils.equals(type, "targetPosition")) {
//            flag = zhijiaService.control(equipmentDO, "onOffStatus", "true");
//        }
//        if (flag && StringUtils.equals(type, "targetPosition")) {
//            type = "openDegree";
//            flag = zhijiaService.control(equipmentDO, type, value);
//        }
        if (flag) {
            try {
                Map<String, String> properties = new HashMap<>();
                if (StringUtils.equals(type, "openDegree")) {
                    properties.put("openDegree", value);
                    properties.put("onOffStatus", "true");
                }
                if (StringUtils.equals(type, "onOffStatus")) {
                    properties.put("onOffStatus", value);
                }
                final Long homeId = equipmentMapper.selectHomeIdByDeviceSn(equipmentDO.getDeviceSn());
                Map<String, Object> cacheMap = zhijiaService.getShadowByDeviceSn(homeId, equipmentDO.getDeptId(), equipmentDO.getDeviceSn());
                Map map = zhijiaService.resolveUhomeDeviceStatus(homeId, equipmentDO, properties, cacheMap);
                CompletableFuture.runAsync(() -> {
                    List<Long> userIds = homeMapper.listUserIdsByDeptId(equipmentDO.getDeptId());
                    Map<String, Object> data = new HashMap<>();
                    data.put("deviceSn", equipmentDO.getDeviceSn());
                    Map<String, Object> propertyMap = new HashMap<>();
                    Boolean onOffStatus = Convert.toBool(map.get("onOffStatus"));
                    propertyMap.put("on", onOffStatus);
                    propertyMap.put("targetPosition", onOffStatus ? map.get("openDegree") : "0");
                    data.put("properties", propertyMap);
                    data.put("deviceType", equipmentDO.getDeviceType());

                    Map<String, Object> pr = new HashMap<>();
                    pr.put("code", HttpStatus.SUCCESS);
                    pr.put("msg", "设备消息");
                    pr.put("type", 3);
                    pr.put("data", data);
                    // 发送属性变化的推送
                    userIds.forEach(userId -> WebsocketManager.appointSending(String.valueOf(userId), JSON.toJSONString(pr)));
                });
            } catch (Exception exception) {
                log.error("控制设备成功，刷新设备影子异常", exception);
            }
        }
        return flag;
    }


    private Map<String, String> positionRange = new HashMap<String, String>(3) {{
        put("min", "0");
        put("max", "100");
        put("step", "1");
    }};

    private List<Map<String, String>> onList = new ArrayList<Map<String, String>>(2) {{
        add(createMap("开", "true"));
        add(createMap("关", "false"));
    }};

    private Map<String, String> createMap(String key, String value) {
        Map<String, String> map = new HashMap<String, String>();
        map.put(key, value);
        return map;
    }
}
